#include "BoundingBox.h"
#include <float.h>
#include <limits>

namespace SEngine
{
    float BoundingBox::Distance(glm::vec3 p)
    {
        float dx = std::max({min.x - p.x, 0.0f, p.x - max.x});
        float dy = std::max({min.y - p.y, 0.0f, p.y - max.y});
        float dz = std::max({min.z - p.z, 0.0f, p.z - max.z});
        return glm::length(glm::vec3(dx, dy, dz));
    }

    bool BoundingBox::Contained(glm::vec3 p)
    {
        return  (p - min).x <= (max - min).x &&
                (p - min).y <= (max - min).y &&
                (p - min).z <= (max - min).z;
    }

    std::array<glm::vec3, 8> BoundingBox::Corners() {
        return {
            glm::vec3{min.x, min.y, min.z}, // 0: 左下后
            glm::vec3{max.x, min.y, min.z}, // 1: 右下后
            glm::vec3{max.x, max.y, min.z}, // 2: 右上前  
            glm::vec3{min.x, max.y, min.z}, // 3: 左上前
            glm::vec3{min.x, min.y, max.z}, // 4: 左下前
            glm::vec3{max.x, min.y, max.z}, // 5: 右下前
            glm::vec3{max.x, max.y, max.z}, // 6: 右上前
            glm::vec3{min.x, max.y, max.z}  // 7: 左上前
        };
    }
    
    std::array<std::pair<glm::vec3, glm::vec3>, 12> BoundingBox::Lines() {
        auto corners = Corners();
        
        // 修正后的边连接索引
        const std::array<std::pair<int, int>, 12> edgeIndices = {{
            {0, 1}, {1, 2}, {2, 3}, {3, 0}, // 底面四条边（z=min.z平面）
            {4, 5}, {5, 6}, {6, 7}, {7, 4}, // 顶面四条边（z=max.z平面）
            {0, 4}, {1, 5}, {2, 6}, {3, 7}  // 侧面四条垂直边
        }};
        
        std::array<std::pair<glm::vec3, glm::vec3>, 12> lines;
        
        for (int i = 0; i < 12; ++i) {
            lines[i] = {corners[edgeIndices[i].first], 
                        corners[edgeIndices[i].second]};
        }
        
        return lines;
    }    

    std::array<BoundingBox, 8> BoundingBox::Split() {
        glm::vec3 center = this->Center();
        auto corners = this->Corners();
        return {
            BoundingBox{glm::min(corners[0], center), glm::max(corners[0], center)},
            BoundingBox{glm::min(corners[1], center), glm::max(corners[1], center)},
            BoundingBox{glm::min(corners[2], center), glm::max(corners[2], center)},
            BoundingBox{glm::min(corners[3], center), glm::max(corners[3], center)},
            BoundingBox{glm::min(corners[4], center), glm::max(corners[4], center)},
            BoundingBox{glm::min(corners[5], center), glm::max(corners[5], center)},
            BoundingBox{glm::min(corners[6], center), glm::max(corners[6], center)},
            BoundingBox{glm::min(corners[7], center), glm::max(corners[7], center)},
        };
    }

    BoundingBox BoundingBox::Transform(glm::mat4 mat)
    {
        // 如果当前包围盒是无效的（未初始化），返回空包围盒
        if (min.x > max.x || min.y > max.y || min.z > max.z) {
            return BoundingBox{};
        }
        
        // 获取原始包围盒的8个角点
        std::array<glm::vec3, 8> corners = Corners();
        
        // 初始化新的最小最大值
        glm::vec3 newMin(std::numeric_limits<float>::max());
        glm::vec3 newMax(-std::numeric_limits<float>::max());
        
        // 对每个角点应用变换，并更新新的包围盒边界
        for (const auto& corner : corners) {
            // 应用变换矩阵（注意使用齐次坐标）
            glm::vec4 transformed = mat * glm::vec4(corner, 1.0f);
            glm::vec3 transformedCorner = glm::vec3(transformed) / transformed.w; // 透视除法
            
            // 更新最小最大值
            newMin = glm::min(newMin, transformedCorner);
            newMax = glm::max(newMax, transformedCorner);
        }
        
        return BoundingBox{newMin, newMax};
    }
    

}
